home *** CD-ROM | disk | FTP | other *** search
- /********************************************************************************/
- /* Smalltalk\Objectworks R4.1 Midi Primitives */
- /* Macintosh System7, GRAME's MidiShare™ and optional Apple's MidiManager */
- /* André Ch. Schnoor, Hamburg (Germany) */
- /* czesanne@mail.hh.provi.de, czesanne@proaudio.de */
- /* */
- /* The following features were included: */
- /* 1) Sequencer-like in/out/start/stop/tempo etc. features */
- /* 2) Bridge to the Apple MidiManager */
- /* */
- /* The MidiManager™ Bridge is partially © GRAME 1991, Yann Orlarey (msPass) */
- /********************************************************************************/
-
- #include "userprim.h"
- #include <MIDI.h>
- #include <Resources.h>
- #include "MidiShare.h"
-
- /********************************************************************************/
- /* Declarations and Prototypes */
- /********************************************************************************/
-
- #define ports 10 // Total of all ports (incl. MidiManager)
- #define midiManagerPort0 9 // Global port used for MidiManager Out0
- #define midiManagerPort1 10 // Global port used for MidiManager Out1
-
- unsigned long preroll = 2000; // Delay (ms) before playing
- unsigned long start = 0; // Time offset (midi ticks)
- unsigned long offset = 0; // Time offset (ms)
- float tempo = 120; // Tempo setting for ms-calculation
- float resolution = 1920; // Resolution (midi ticks p. 4/4)
-
- /********************************************************************************/
- /* GRAME's MidiShare */
- /********************************************************************************/
- #define midiShareRefName "\pSmalltalk™"
- #define midiShareBridgeName "\pSt-Bridge"
- #define midiShareLinkName "\pSt-Link"
-
- short midiShareRef = 0; // MidiShare™ ref. for phys. output
- short midiShareLink = 0; // MidiShare™ ref. for linking MidiManager
- short midiShareBridge = 0; // MidiShare™ ref. attached to MidiManager
-
- /********************************************************************************/
- /* Apple's MidiManager */
- /********************************************************************************/
- #define appName "\pSmalltalk-80™"
- #define appID 'ST8M'
-
- short midiManagerRefOut [2]; // port handles for output
- short midiManagerRefIn [2]; // port handles for input
- short midiManagerTime; // port for time sync
-
- Boolean bridgeInstalled = false; // MidiShare => MidiManager?
-
- /********************************************************************************/
- /* */
- /********************************************************************************/
-
- #define timePortBuffSize 256L
- #define inputPortBuffSize 2048L
- #define outputPortBuffSize 256L
-
- /********************************************************************************/
- /* Functions */
- /********************************************************************************/
-
- Boolean MidiSystemOpen (); // Install all available Midi features
- Boolean MidiSystemStop (); // Stop playing
- Boolean MidiSystemClose (); // Uninstall everything
-
- Boolean MidiBridgeClose ();
-
- long ms ( long ticks ); // Convert ticks->clock according current tempo/res.
- long ticks ( long ms ); // Convert vice versa
-
- void Send ( MidiEvPtr e ); // Send MidiShare Event at designated time
- void Sequence ( MidiEvPtr e ); // Send event to sequencer queue
- void SendNow ( MidiEvPtr e ); // Send event immediately
-
- void SendAllNotesOff (
- long clock,
- int port,
- int chan);
-
- void SendNoteEvent (
- long clock,
- int port,
- int chan,
- int pitch,
- int vel,
- int dur);
-
- void SendControlEvent (
- long clock,
- int port,
- int chan,
- int controller,
- int value);
-
- void SendProgramEvent (
- long clock,
- int port,
- int chan,
- int program);
-
- /********************************************************************************/
- /* Sequencer */
- /********************************************************************************/
-
- #define idle 0
- #define playing 1
-
- short sequencerState = idle;
- MidiSeqPtr sequence;
- MidiEvPtr sequenceTask;
-
- void OpenSequencer ()
- {
- sequencerState = idle; // first state is idle
- sequence = MidiNewSeq(); // create an empty sequence
- sequenceTask = 0; // no task at the momment
- }
-
-
- void StopSequencer ()
- {
- switch (sequencerState) {
- case playing : // stop playing
- MidiForgetTask(&sequenceTask); // forget the current play task
- sequencerState = idle;
- MidiClearSeq(sequence); // clear sequence contents
- break;
-
- case idle :
- MidiClearSeq(sequence); // clear sequence contents
- break;
- }
- }
-
- void CloseSequencer ()
- {
- StopSequencer(); // stop current activities
- MidiFreeSeq(sequence); // free the sequence
- }
-
-
- pascal void PlayTask (long date, short refNum, MidiEvPtr e, long d, long unused )
- {
- d = Date(e); // remember the date of the current event to play
- while (e && (Date(e) == d)) { // for all the events at this date
- SendNow(MidiCopyEv(e));
- e = Link(e); // go to next event
- };
-
- if (e) { // if not the end, schedule the task for next event
- sequenceTask = MidiTask(
- (TaskPtr)PlayTask,
- date + Date(e) - d,
- refNum,
- (long)e,
- 0,
- 0);
-
- } else {
- sequencerState = idle;
- sequenceTask = 0;
- }
- }
-
-
- Boolean StartSequencer ()
- {
- MidiEvPtr e;
-
- if (sequencerState == playing) return false;
-
- if (e = First(sequence)) {
- sequencerState = playing;
- PlayTask(MidiGetTime(), midiShareRef, e, 0, 0);
- };
- return true;
- }
-
- /********************************************************************************/
- /* */
- /********************************************************************************/
-
- typedef struct TScanner * ScannerPtr; // Scanner for SYSEX streams
- typedef struct TScanner
- {
- long length;
- MidiSEXPtr block;
- long pos;
- int index;
- } TScanner;
-
- typedef struct TFormatter * FormatterPtr; // Formatter for SYSEX streams
- typedef struct TFormatter
- {
- long num; // numéro du packet courant (à partir de 0)
- int index; // index dans le packet courant [0..248]
- short port; // refnum du port MidiManager
- MIDIPacket packet; // packet MidiManager
- } TFormatter;
-
- TFilter myFilter; // filtre pour les événements Midi
- MidiEvPtr PendingEv[2]; // Evénements en cours de construction
-
- /********************************************************************************/
- /* Conversion Tables */
- /********************************************************************************/
-
- typedef void (* ms2mmfp) (MidiEvPtr e); // MidiShare events ==> MidiManager packets
- ms2mmfp ms2mmtbl[256];
-
- typedef void (* mm2msfp) (MIDIPacket * m, short port, short chan);
- mm2msfp mm2mstbl[8]; // MidiManager packets ==> MidiShare events
-
- typedef void (* rt2msfp) (MIDIPacket * m, short port);
- rt2msfp rt2mstbl[16];
-
- /********************************************************************************/
- /* String Operations */
- /********************************************************************************/
-
- void InsertCh( Str255 s, short p, char c) /* Insert un caractère dans une
- chaine Pascal */
- { /* à partir de la position p (de 1 à n). */
- register short n;
- register char t;
-
- if (p >= s[0])
- s[s[0]] = c;
- else
- for (n= s[0]-p; n>=0; n--, p++) { t=c; c=s[p]; s[p]=t; }
- s[0]++;
- }
-
- void ShiftPStr( Str255 s, short n ) /* Décale une chaine Pascal de n
- caractères */
- { /* vers la droite. */
- register char *ps;
- register char *pd;
-
- ps = (char*)s + s[0];
- pd = ps + n;
- s[0] += n;
- for (; n>0; n--) *pd-- = *ps-- ;
- }
-
- void TransfPStr(Str255 s1, char* s2, short n) /* Ecrase le début de la
- chaine s1 avec s2 */
- {
- for (; n>0; n--) *++s1 = *++s2 ;
- }
-
- void AddFirst( Str255 s1, char * s2) /* Insere en début de la chaine s1
- la chaine s2 */
- {
- ShiftPStr( s1, s2[0] );
- TransfPStr( s1, s2, s2[0] );
- }
-
- void myC2PStr ( char* cs, Str255 ps)
- {
- int i;
-
- for (i=0; cs[i]; i++) ps[i+1] = cs[i];
- ps[0] = i;
- }
-
- /********************************************************************************/
- /* */
- /********************************************************************************/
-
- void InitFormat (FormatterPtr f, short p)
- {
- f->num = 0; f->index = 0; f->port = p;
- }
-
- void Format (FormatterPtr f, short v)
- {
- if (f->index > 248) {
- if (f->num == 0)
- f->packet.flags = midiTimeStampCurrent | midiStartCont;
- else
- f->packet.flags = midiTimeStampCurrent | midiMidCont;
- f->packet.len = 255;
- MIDIWritePacket( f->port, &(f->packet) );
- f->index = 0;
- f->num++;
- }
- f->packet.data[f->index] = v;
- f->index++;
- }
-
- void StopFormat (FormatterPtr f)
- {
- f->packet.len = f->index + 6;
- if (f->num == 0)
- f->packet.flags = midiTimeStampCurrent | midiNoCont;
- else
- f->packet.flags = midiTimeStampCurrent | midiEndCont;
- MIDIWritePacket( f->port, &(f->packet) );
- }
-
-
- /********************************************************************************/
- /* */
- /********************************************************************************/
-
- long InitScanner (ScannerPtr s, MidiEvPtr e)
- {
- s->length = MidiCountFields(e);
- s->pos = 0;
- s->index = 0;
- s->block = Link(LinkSE(e));
- return s->length;
- }
-
- long RemainToScan (ScannerPtr s)
- {
- if (s->pos < s->length)
- return s->length - s->pos;
- else
- return 0;
- }
-
- int Scan (ScannerPtr s)
- {
- int b;
-
- if (s->pos >= s->length) return -1;
- b = s->block->data[s->index];
- s->pos++;
- s->index++;
- if (s->index >= 12) {
- s->index = 0;
- s->block = Link(s->block);
- }
- return b;
- }
-
- /********************************************************************************/
- /* */
- /********************************************************************************/
-
- void SendNothing (MidiEvPtr e)
- {
- MidiFreeEv(e);
- }
-
-
- void SendKeyOn (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 9;
-
- // send note on.
- TheMIDIPacket.data[0] = Chan(e) + NoteOn;
- TheMIDIPacket.data[1] = Pitch(e);
- TheMIDIPacket.data[2] = Vel(e);
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- MidiFreeEv(e);
- }
-
-
- void SendKeyOff (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 9;
-
- // send note off.
- TheMIDIPacket.data[0] = Chan(e) + NoteOff;
- TheMIDIPacket.data[1] = Pitch(e);
- TheMIDIPacket.data[2] = Vel(e);
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- MidiFreeEv(e);
- }
-
-
- void SendNote (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 9;
-
- // send note on.
- TheMIDIPacket.data[0] = Chan(e) + NoteOn;
- TheMIDIPacket.data[1] = Pitch(e);
- TheMIDIPacket.data[2] = Vel(e);
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- // transform e into a note off.
- EvType(e) = typeKeyOff; // has been typeKeyOn!
- Date(e) += Dur(e);
- Vel(e) = 0;
- MidiSend(midiShareBridge+128, e);
- }
-
-
- void SendKeyPress (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 9;
- TheMIDIPacket.data[0] = Chan(e) + PolyTouch;
- TheMIDIPacket.data[1] = Pitch(e);
- TheMIDIPacket.data[2] = Vel(e);
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- MidiFreeEv(e);
- }
-
-
- void SendCtrlChange (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 9;
- TheMIDIPacket.data[0] = Chan(e) + ControlChg;
- TheMIDIPacket.data[1] = Pitch(e);
- TheMIDIPacket.data[2] = Vel(e);
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- MidiFreeEv(e);
- }
-
-
- void SendProgChange (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 8;
- TheMIDIPacket.data[0] = Chan(e) + ProgramChg;
- TheMIDIPacket.data[1] = Pitch(e);
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- MidiFreeEv(e);
- }
-
-
- void SendChanPress (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 8;
- TheMIDIPacket.data[0] = Chan(e) + AfterTouch;
- TheMIDIPacket.data[1] = Pitch(e);
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- MidiFreeEv(e);
- }
-
-
- void SendPitchWheel (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 9;
- TheMIDIPacket.data[0] = Chan(e) + PitchBend;
- TheMIDIPacket.data[1] = Pitch(e);
- TheMIDIPacket.data[2] = Vel(e);
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- MidiFreeEv(e);
- }
-
-
- void SendSongPos (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 9;
- TheMIDIPacket.data[0] = SongPos;
- TheMIDIPacket.data[1] = Pitch(e);
- TheMIDIPacket.data[2] = Vel(e);
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- MidiFreeEv(e);
- }
-
-
- void SendSongSel (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 8;
- TheMIDIPacket.data[0] = SongSel;
- TheMIDIPacket.data[1] = Pitch(e);
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- MidiFreeEv(e);
- }
-
-
- void SendClock (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 7;
- TheMIDIPacket.data[0] = MClock;
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- MidiFreeEv(e);
- }
-
-
- void SendStart (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 7;
- TheMIDIPacket.data[0] = MStart;
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- MidiFreeEv(e);
- }
-
-
- void SendContinue (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 7;
- TheMIDIPacket.data[0] = MCont;
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- MidiFreeEv(e);
- }
-
-
- void SendStop (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 7;
- TheMIDIPacket.data[0] = MStop;
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- MidiFreeEv(e);
- }
-
-
- void SendTune (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 7;
- TheMIDIPacket.data[0] = Tune;
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- MidiFreeEv(e);
- }
-
-
- void SendActiveSens (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 7;
- TheMIDIPacket.data[0] = ActSense;
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- MidiFreeEv(e);
- }
-
-
- void SendReset (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 7;
- TheMIDIPacket.data[0] = MReset;
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- MidiFreeEv(e);
- }
-
-
- void SendQuarterFrame (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = 8;
- TheMIDIPacket.data[0] = QFrame;
- TheMIDIPacket.data[1] = (Pitch(e) << 4) | Vel(e);
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
-
- MidiFreeEv(e);
- }
-
- void oldSendSysEx (MidiEvPtr e)
- {
- MIDIPacket TheMIDIPacket;
- TScanner s;
- long i;
-
- InitScanner(&s, e);
- if (s.length <= 247) {
-
- TheMIDIPacket.flags = 0x80;
- TheMIDIPacket.len = s.length + 6 + 2;
- TheMIDIPacket.data[0] = SysEx;
- for (i=1; RemainToScan(&s); i++) TheMIDIPacket.data[i] = Scan(&s);
- TheMIDIPacket.data[i] = EndSysX;
- MIDIWritePacket(midiManagerRefOut[Port(e)], &TheMIDIPacket);
- }
-
- MidiFreeEv(e);
- }
-
- void SendSysEx (MidiEvPtr e)
- {
- TFormatter f;
- TScanner s;
-
- InitScanner(&s, e);
- InitFormat(&f, midiManagerRefOut[Port(e)]);
-
- Format(&f, SysEx);
- while (RemainToScan(&s)) Format(&f, Scan(&s));
- Format(&f, EndSysX);
- StopFormat(&f);
-
- MidiFreeEv(e);
- }
-
- void SendStream (MidiEvPtr e)
- {
- TFormatter f1, f2;
- TScanner s;
- int v;
- short p;
-
- p = midiManagerRefOut[Port(e)];
- InitScanner(&s, e);
-
- for (v = Scan(&s); v >= 0;) {
- if ( v == SysEx ) {
- InitFormat(&f1, p);
- Format(&f1, v);
- for (v = Scan(&s); (v >= 0) && ((v < 128) || (v > EndSysX)) ; v = Scan(&s)) {
- if (v > EndSysX) {
- // message imbriqué
- InitFormat(&f2, p); Format(&f2, v); StopFormat(&f2);
- } else {
- Format(&f1, v);
- }
- }
- if (v == EndSysX) v = Scan(&s);
- Format(&f1, EndSysX);
- StopFormat(&f1);
- }else if ((v >= NoteOff) && (v != EndSysX)) {
- InitFormat(&f1, p);
- Format(&f1, v);
- for (v = Scan(&s); (v >= 0) && (v < 128); v = Scan(&s)) Format(&f1, v);
- StopFormat(&f1);
- }
- }
-
- MidiFreeEv(e);
- }
-
-
- void InitMs2MMtbl (void)
- {
- int i;
-
- for (i = 0; i<256; i++) ms2mmtbl[i] = SendNothing;
- ms2mmtbl[typeNote] = SendNote;
- ms2mmtbl[typeKeyOn] = SendKeyOn;
- ms2mmtbl[typeKeyOff] = SendKeyOff;
- ms2mmtbl[typeKeyPress] = SendKeyPress;
- ms2mmtbl[typeCtrlChange] = SendCtrlChange;
- ms2mmtbl[typeProgChange] = SendProgChange;
- ms2mmtbl[typeChanPress] = SendChanPress;
- ms2mmtbl[typePitchWheel] = SendPitchWheel;
- ms2mmtbl[typeSongPos] = SendSongPos;
- ms2mmtbl[typeSongSel] = SendSongSel;
- ms2mmtbl[typeClock] = SendClock;
- ms2mmtbl[typeStart] = SendStart;
- ms2mmtbl[typeContinue] = SendContinue;
- ms2mmtbl[typeStop] = SendStop;
- ms2mmtbl[typeTune] = SendTune;
- ms2mmtbl[typeActiveSens] = SendActiveSens;
- ms2mmtbl[typeReset] = SendReset;
- ms2mmtbl[typeSysEx] = SendSysEx;
- ms2mmtbl[typeStream] = SendStream;
- ms2mmtbl[typeQuarterFrame] = SendQuarterFrame;
- }
-
- /********************************************************************************/
- /* */
- /********************************************************************************/
-
- void ReadKeyOff (MIDIPacket * m, short port, short chan)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeKeyOff)) {
- Port(e) = port;
- Chan(e) = chan;
- Pitch(e)= m->data[1];
- Vel(e) = m->data[2];
- MidiSendIm(midiShareBridge, e);
- }
- }
-
- void ReadKeyOn (MIDIPacket * m, short port, short chan)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeKeyOn)) {
- Port(e) = port;
- Chan(e) = chan;
- Pitch(e)= m->data[1];
- Vel(e) = m->data[2];
- MidiSendIm(midiShareBridge, e);
- }
- }
-
- void ReadKeyPress (MIDIPacket * m, short port, short chan)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeKeyPress)) {
- Port(e) = port;
- Chan(e) = chan;
- Pitch(e)= m->data[1];
- Vel(e) = m->data[2];
- MidiSendIm(midiShareBridge, e);
- }
- }
-
- void ReadCtrlChange (MIDIPacket * m, short port, short chan)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeCtrlChange)) {
- Port(e) = port;
- Chan(e) = chan;
- Pitch(e)= m->data[1];
- Vel(e) = m->data[2];
- MidiSendIm(midiShareBridge, e);
- }
- }
-
- void ReadProgChange (MIDIPacket * m, short port, short chan)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeProgChange)) {
- Port(e) = port;
- Chan(e) = chan;
- Pitch(e)= m->data[1];
- MidiSendIm(midiShareBridge, e);
- }
- }
-
- void ReadChanPress (MIDIPacket * m, short port, short chan)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeChanPress)) {
- Port(e) = port;
- Chan(e) = chan;
- Pitch(e)= m->data[1];
- MidiSendIm(midiShareBridge, e);
- }
- }
-
- void ReadPitchWheel (MIDIPacket * m, short port, short chan)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typePitchWheel)) {
- Port(e) = port;
- Chan(e) = chan;
- Pitch(e)= m->data[1];
- Vel(e) = m->data[2];
- MidiSendIm(midiShareBridge, e);
- }
- }
-
-
- void ReadSmallSysEx (MIDIPacket * m, short port)
- {
- MidiEvPtr e;
- int i;
- int j;
-
- if (e = MidiNewEv(typeSysEx)) {
- for (i=1, j=m->len-6; (i<j) && ( m->data[i] < 128 ); i++)
- MidiAddField(e, m->data[i]);
- Port(e) = port;
- Chan(e) = 0;
- MidiSendIm(midiShareBridge, e);
- }
- }
-
- void ReadStartCont (MIDIPacket * m, short port)
- {
- MidiEvPtr e;
- int i,j;
-
- if (e = PendingEv[port]) {
- MidiFreeEv(e);
- e = nil;
- }
- if (m->data[0] == SysEx) {
- if (e = MidiNewEv(typeSysEx)) {
- for (i=1, j=m->len-6; (i<j) && ( m->data[i] < 128 ); i++)
- MidiAddField(e, m->data[i]);
- Port(e) = port;
- Chan(e) = 0;
- }
- } else {
- if (e = MidiNewEv(typeStream)) {
- for (i=0, j=m->len-6; i<j; i++) MidiAddField(e, m->data[i]);
- Port(e) = port;
- Chan(e) = 0;
- }
- }
- PendingEv[port] = e;
- }
-
- void ReadMidCont (MIDIPacket * m, short port)
- {
- MidiEvPtr e;
- int i,j;
-
- if (e = PendingEv[port]) {
- if (EvType(e) == typeSysEx) {
- for (i=0, j=m->len-6; (i<j) && ( m->data[i] < 128 ); i++)
- MidiAddField(e, m->data[i]);
- } else if (EvType(e) == typeStream) {
- for (i=0, j=m->len-6; i<j; i++)
- MidiAddField(e, m->data[i]);
- }
- }
- }
-
- void ReadEndCont (MIDIPacket * m, short port)
- {
- MidiEvPtr e;
- int i,j;
-
- if (e = PendingEv[port]) {
- if (EvType(e) == typeSysEx) {
- for (i=0, j=m->len-6; (i<j) && ( m->data[i] < 128 ); i++)
- MidiAddField(e, m->data[i]);
- } else if (EvType(e) == typeStream) {
- for (i=0, j=m->len-6; i<j; i++)
- MidiAddField(e, m->data[i]);
- }
- MidiSendIm(midiShareBridge, e);
- PendingEv[port] = nil;
- }
- }
-
-
- void ReadQuarterFrame (MIDIPacket * m, short port)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeQuarterFrame)) {
- Port(e) = port;
- Chan(e) = 0;
- Pitch(e)= m->data[1] >> 4;
- Vel(e) = m->data[1] & 0xF;
- MidiSendIm(midiShareBridge, e);
- }
- }
-
- void ReadSongPos (MIDIPacket * m, short port)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeSongPos)) {
- Port(e) = port;
- Chan(e) = 0;
- Pitch(e)= m->data[1];
- Vel(e) = m->data[2];
- MidiSendIm(midiShareBridge, e);
- }
- }
-
- void ReadSongSel (MIDIPacket * m, short port)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeSongSel)) {
- Port(e) = port;
- Chan(e) = 0;
- Pitch(e)= m->data[1];
- MidiSendIm(midiShareBridge, e);
- }
- }
-
- void ReadClock (MIDIPacket *, short port)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeClock)) {
- Port(e) = port;
- Chan(e) = 0;
- MidiSendIm(midiShareBridge, e);
- }
- }
-
- void ReadStart (MIDIPacket *, short port)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeStart)) {
- Port(e) = port;
- Chan(e) = 0;
- MidiSendIm(midiShareBridge, e);
- }
- }
-
- void ReadContinue (MIDIPacket *, short port)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeContinue)) {
- Port(e) = port;
- Chan(e) = 0;
- MidiSendIm(midiShareBridge, e);
- }
- }
-
- void ReadStop (MIDIPacket *, short port)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeStop)) {
- Port(e) = port;
- Chan(e) = 0;
- MidiSendIm(midiShareBridge, e);
- }
- }
-
- void ReadTune (MIDIPacket *, short port)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeTune)) {
- Port(e) = port;
- Chan(e) = 0;
- MidiSendIm(midiShareBridge, e);
- }
- }
-
- void ReadActiveSens (MIDIPacket *, short port)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeActiveSens)) {
- Port(e) = port;
- Chan(e) = 0;
- MidiSendIm(midiShareBridge, e);
- }
- }
-
- void ReadReset (MIDIPacket *, short port)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeReset)) {
- Port(e) = port;
- Chan(e) = 0;
- MidiSendIm(midiShareBridge, e);
- }
- }
-
- void ReadUndef (MIDIPacket *, short)
- {
- }
-
- void ReadNonChan (MIDIPacket * m, short port, short chan)
- {
- (*rt2mstbl[chan])(m, port);
- }
-
- void initmm2mstbl(void)
- {
-
- // table principale
- mm2mstbl[0] = ReadKeyOff;
- mm2mstbl[1] = ReadKeyOn;
- mm2mstbl[2] = ReadKeyPress;
- mm2mstbl[3] = ReadCtrlChange;
- mm2mstbl[4] = ReadProgChange;
- mm2mstbl[5] = ReadChanPress;
- mm2mstbl[6] = ReadPitchWheel;
- mm2mstbl[7] = ReadNonChan;
-
- // table secondaire pour les messages sans canaux
- rt2mstbl[0] = ReadSmallSysEx;
- rt2mstbl[1] = ReadQuarterFrame;
- rt2mstbl[2] = ReadSongPos;
- rt2mstbl[3] = ReadSongSel;
- rt2mstbl[4] = ReadUndef;
- rt2mstbl[5] = ReadUndef;
- rt2mstbl[6] = ReadTune;
- rt2mstbl[7] = ReadUndef; // end of sysex
- rt2mstbl[8] = ReadClock;
- rt2mstbl[9] = ReadUndef;
- rt2mstbl[10] = ReadStart;
- rt2mstbl[11] = ReadContinue;
- rt2mstbl[12] = ReadStop;
- rt2mstbl[13] = ReadUndef;
- rt2mstbl[14] = ReadActiveSens;
- rt2mstbl[15] = ReadReset;
- }
-
-
- void ReadMessage (MIDIPacket * m, short port)
- {
- unsigned char status;
-
-
- if (((m->flags) & midiContMask) == midiNoCont) {
- status = m->data[0];
- if (status >= NoteOff)
- (*mm2mstbl[(status >> 4) & 7])(m, port, status & 0xF);
- } else if (((m->flags) & midiContMask) == midiStartCont) {
- ReadStartCont(m, port);
- } else if (((m->flags) & midiContMask) == midiMidCont) {
- ReadMidCont(m, port);
- } else if (((m->flags) & midiContMask) == midiEndCont) {
- ReadEndCont(m, port);
- }
- }
-
- pascal short mmReader0 (MIDIPacket * m, long myA5)
- {
- long sysA5 = SetA5(myA5);
-
- if (((m->flags) & midiTypeMask) == midiMsgType)
- ReadMessage(m, 0);
- SetA5(sysA5);
- return midiMorePacket;
- }
-
-
- pascal short mmReader1 (MIDIPacket * m, long myA5)
- {
- long sysA5 = SetA5(myA5);
-
- if (((m->flags) & midiTypeMask) == midiMsgType)
- ReadMessage(m, 1);
- SetA5(sysA5);
- return midiMorePacket;
- }
-
-
- /********************************************************************************/
- /* MidiManager Part */
- /********************************************************************************/
-
-
- void CloseMidiManager (void)
- {
- MIDISignOut(appID);
- }
-
-
- Boolean SetUpMidiManager (void)
- {
- MIDIPortParams pparams; // MIDI Mgr pparams data structure
- Handle icon;
- OSErr err;
-
-
- // Sign in into MidiManager
-
- icon = GetResource('ICN#', 128);
- err = MIDISignIn(appID, 0L, icon, appName);
- if (err) return false;
-
-
- // Add a time port.
-
- pparams.portID = 'time';
- pparams.portType = midiPortTypeTimeInv; // le port est invisible
- pparams.timeBase = NULL;
- pparams.readHook = NULL;
- pparams.initClock.sync = midiInternalSync;
- pparams.initClock.curTime = 0;
- pparams.initClock.format = midiFormatMSec;
- pparams.refCon = NULL;
- myC2PStr("TimeBase", pparams.name);
-
- (void) MIDIAddPort(appID, timePortBuffSize, &midiManagerTime, &pparams);
-
-
- // Add input port 0.
-
- pparams.portID = 'in 0';
- pparams.portType = midiPortTypeInput;
- pparams.timeBase = midiManagerTime;
- pparams.offsetTime = midiGetCurrent;
- pparams.readHook = (Ptr)mmReader0;
- pparams.refCon = SetCurrentA5();
- myC2PStr("In0", pparams.name);
-
- (void) MIDIAddPort(appID, inputPortBuffSize, &midiManagerRefIn[0], &pparams);
-
-
- // Add input port 1.
-
- pparams.portID = 'in 1';
- pparams.portType = midiPortTypeInput;
- pparams.timeBase = midiManagerTime;
- pparams.offsetTime = midiGetCurrent;
- pparams.readHook = (Ptr)mmReader1;
- pparams.refCon = SetCurrentA5();
- myC2PStr("In1", pparams.name);
-
- (void) MIDIAddPort(appID, inputPortBuffSize, &midiManagerRefIn[1], &pparams);
-
-
- // Add output port 0.
-
- pparams.portID = 'out0';
- pparams.portType = midiPortTypeOutput;
- pparams.timeBase = midiManagerTime;
- pparams.offsetTime = midiGetCurrent;
- pparams.readHook = NULL;
- pparams.refCon = NULL;
- myC2PStr("Out0", pparams.name);
-
- (void) MIDIAddPort(appID, outputPortBuffSize, &midiManagerRefOut[0], &pparams);
-
-
- // Add output port 1.
-
- pparams.portID = 'out1';
- pparams.portType = midiPortTypeOutput;
- pparams.timeBase = midiManagerTime;
- pparams.offsetTime = midiGetCurrent;
- pparams.readHook = NULL;
- pparams.refCon = NULL;
- myC2PStr("Out1", pparams.name);
-
- (void) MIDIAddPort(appID, outputPortBuffSize, &midiManagerRefOut[1], &pparams);
-
-
- // Start our Clock.
-
- MIDIStartTime(midiManagerTime);
- initmm2mstbl();
-
- return true;
- }
-
- /********************************************************************************/
- /* MidiShare Part */
- /********************************************************************************/
-
- pascal void TransferEventsToMidiManager (short r)
- {
- MidiEvPtr e;
-
- while (e = MidiGetEv(r)) {
- (*ms2mmtbl[e->evType])(e);
- }
- }
-
-
- void InstallFilter ()
- {
- register short i;
-
- for (i = 0; i<256; i++)
- {
- AcceptBit(myFilter.evType,i); /* accepte tous les types d'événements */
- RejectBit(myFilter.port,i); /* refuse tous les ports */
- }
- AcceptBit(myFilter.port,0); /* accept le port 0 */
- AcceptBit(myFilter.port,1); /* accept le port 1 */
-
- for (i = 0; i<16; i++)
- AcceptBit(myFilter.channel,i); /* et sur tous les canaux Midi */
-
- MidiSetFilter( midiShareBridge, &myFilter ); /* installe le filtre */
- }
-
- /********************************************************************************/
- /* Receiving to Smalltalk */
- /********************************************************************************/
-
- TFilter receiveFilter;
-
-
- void InstallReceiveFilter ( short ref )
- {
- register short i;
-
- for (i = 0; i < 256; i++) {
- RejectBit(receiveFilter.evType,i);
- RejectBit(receiveFilter.port,i);
- }
- for (i = 0; i < 8; i++) AcceptBit(receiveFilter.port,i);
- for (i = 0; i < 16; i++) AcceptBit(receiveFilter.channel,i);
-
- AcceptBit(receiveFilter.evType,typeNote);
- AcceptBit(receiveFilter.evType,typeKeyOn);
- AcceptBit(receiveFilter.evType,typeKeyOff);
- AcceptBit(receiveFilter.evType,typeCtrlChange);
- AcceptBit(receiveFilter.evType,typeProgChange);
-
- MidiSetFilter( ref, &receiveFilter );
- }
-
- void UPMidiGetEvent ( upHandle rcvr )
- {
- upHandle answer;
- MidiEvPtr e;
-
- if (e = MidiGetEv(midiShareRef)) {
- answer = UPallocByteArray((upByte)0,(upInt)sizeof(TMidiEv));
- (void)UPcopyCtoSTbytes(answer,e,(upInt)sizeof(TMidiEv),1L);
- MidiFreeEv(e);
- UPreturnHandle(answer);
- }
- else UPreturnNil();
- }
-
-
- void UPMidiClearEvents ( upHandle rcvr )
- {
- MidiFlushEvs(midiShareRef);
- UPreturnTrue();
- }
-
-
- /********************************************************************************/
- /* MidiManager Bridge */
- /********************************************************************************/
-
- Boolean MidiManager ()
- {
- return true;
- }
-
-
- Boolean MidiBridgeOpen ()
- {
- if (bridgeInstalled) MidiBridgeClose();
-
- bridgeInstalled = false;
-
- if (!MidiManager()) return false;
-
- if ((midiShareBridge = MidiOpen(midiShareBridgeName)) == MIDIerrSpace)
- return false;
-
- if ((midiShareLink = MidiOpen(midiShareLinkName)) == MIDIerrSpace) {
- MidiClose(midiShareBridge);
- return false;
- };
-
- InstallFilter();
- InitMs2MMtbl();
-
- if (!SetUpMidiManager()) {
- MidiClose(midiShareBridge);
- MidiClose(midiShareLink);
- return false;
- };
-
- MidiSetRcvAlarm(midiShareBridge, TransferEventsToMidiManager);
- MidiConnect(midiShareLink, midiShareBridge, true);
-
- bridgeInstalled = true;
- return true;
- }
-
-
- Boolean MidiBridgeClose ()
- {
- if (!bridgeInstalled) return false;
-
- bridgeInstalled = false;
-
- MIDISignOut(appID);
- MidiClose(midiShareLink);
- MidiClose(midiShareBridge);
-
- return true;
- }
-
-
- /********************************************************************************/
- /* Opening/Closing */
- /********************************************************************************/
-
- Boolean MidiSystemOpen ()
- {
- if (!MidiShare()) return false;
- if ((midiShareRef = MidiOpen(midiShareRefName)) == MIDIerrSpace) return false;
-
- MidiConnect(midiShareRef, 0, true); // physical output
- MidiConnect(0, midiShareRef, true); // physical input
- InstallReceiveFilter(midiShareRef); // filter out events useless for Leviathan
-
- if (MidiManager()) MidiBridgeOpen();
- OpenSequencer();
- return true;
- }
-
- Boolean MidiSystemClose ()
- {
- if (!MidiShare()) return false;
-
- CloseSequencer();
- MidiClose(midiShareRef);
- if (MidiManager()) MidiBridgeClose();
-
- return true;
- }
-
- Boolean MidiSystemStop ()
- {
- if (!MidiShare()) return false;
-
- StopSequencer();
- return true;
- }
-
- /********************************************************************************/
- /* User Primitives */
- /********************************************************************************/
-
- void UPMidiSharePresent ( upHandle rcvr ) { UPreturnHandle( UPCtoSTbool( MidiShare()));}
- void UPMidiGetVersion ( upHandle rcvr ) { UPreturnHandle( UPCtoSTint( MidiGetVersion()));}
- void UPMidiOpen ( upHandle rcvr ) { UPreturnHandle( UPCtoSTbool( MidiSystemOpen()));}
- void UPMidiClose ( upHandle rcvr ) { UPreturnHandle( UPCtoSTbool( MidiSystemClose()));}
- void UPMidiStart ( upHandle rcvr ) { UPreturnHandle( UPCtoSTbool( StartSequencer()));}
- void UPMidiStop ( upHandle rcvr ) { UPreturnHandle( UPCtoSTbool( MidiSystemStop()));}
- void UPMidiGetTime ( upHandle rcvr ) { UPreturnHandle( UPCtoSTint( MidiGetTime()));}
- void UPMidiGetClock ( upHandle rcvr ) { UPreturnHandle( UPCtoSTint( ticks(MidiGetTime())));}
- void UPMidiGetTotalSpace ( upHandle rcvr ){ UPreturnHandle( UPCtoSTint( MidiTotalSpace()));}
- void UPMidiGetFreeSpace ( upHandle rcvr ) { UPreturnHandle( UPCtoSTint( MidiFreeSpace()));}
-
-
- void UPMidiSetTiming (
- upHandle rcvr,
- upHandle startInteger,
- upHandle tempoInteger,
- upHandle resolutionInteger,
- upHandle delayInteger )
- {
- StopSequencer();
-
- offset = MidiGetTime() + UPSTtoCint( delayInteger );
- start = UPSTtoCint( startInteger );
- tempo = UPSTtoCint( tempoInteger );
- resolution = UPSTtoCint( resolutionInteger );
- UPreturnHandle(UPCtoSTint(0));
- }
-
-
- /********************************************************************************/
- /* CONVERTING TIME (ms/ticks) */
- /********************************************************************************/
-
- long ms ( long ticks )
- {
- return 240000.0 * ticks / (tempo * resolution);
- }
-
- long ticks ( long ms )
- {
- return (ms * tempo * resolution) / 240000.0;
- }
-
- /********************************************************************************/
- /* SENDING EVENTS */
- /********************************************************************************/
-
-
- void Sequence ( MidiEvPtr e )
- {
- MidiAddSeq(sequence,e);
- }
-
-
- void SendNow ( MidiEvPtr e )
- {
- if ( Port(e) == midiManagerPort0) {
- Port(e) = 0;
- MidiSendIm(midiShareLink,e);
- return;
- }
-
- if ( Port(e) == midiManagerPort1 ) {
- Port(e) = 1;
- MidiSendIm(midiShareLink,e);
- return;
- }
-
- MidiSendIm(midiShareRef,e);
- }
-
-
- void Send ( MidiEvPtr e )
- {
- if ( Port(e) == midiManagerPort0) {
- Port(e) = 0;
- MidiSend(midiShareLink,e);
- return;
- }
-
- if ( Port(e) == midiManagerPort1 ) {
- Port(e) = 1;
- MidiSend(midiShareLink,e);
- return;
- }
-
- MidiSend(midiShareRef,e);
- }
-
-
-
- void SendNoteEvent (
- long date,
- int port,
- int chan,
- int pitch,
- int vel,
- int dur)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeNote)) {
- Date(e) = date;
- Chan(e) = chan;
- Port(e) = port;
- Pitch(e) = pitch;
- Vel(e) = vel;
- Dur(e) = ms(dur);
-
- Sequence(e);
- }
- }
-
- void SendControlEvent (
- long date,
- int port,
- int chan,
- int controller,
- int value)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeCtrlChange)) {
- Date(e) = date;
- Chan(e) = chan;
- Port(e) = port;
- MidiSetField(e,0,controller);
- MidiSetField(e,1,value);
-
- Sequence(e);
- }
- }
-
- void SendAllNotesOff (
- long date,
- int port,
- int chan)
- {
- MidiEvPtr e;
- register int pitch;
-
- for (pitch = 0; pitch < 127; pitch++) {
- if (e = MidiNewEv(typeKeyOff)) {
- Date(e) = date;
- Chan(e) = chan;
- Port(e) = port;
- Pitch(e) = pitch;
-
- Send(e);
- }
- }
- }
-
-
- void SendProgramEvent (
- long date,
- int port,
- int chan,
- int program)
- {
- MidiEvPtr e;
-
- if (e = MidiNewEv(typeProgChange)) {
- Date(e) = date;
- Chan(e) = chan;
- Port(e) = port;
- MidiSetField(e,0,program);
-
- Sequence(e);
- }
- }
-
-
- void UPMidiSendEvent (
- upHandle rcvr,
- upHandle clock,
- upHandle port,
- upHandle chan,
- upHandle type,
- upHandle data1, /* pitch, controller no., program no. */
- upHandle data2, /* velocity, controller value */
- upHandle data3 /* duration */ )
- {
- long date;
-
- date = offset + ms(UPSTtoCint(clock) - start);
-
- switch (UPSTtoCint(type)) {
-
- case typeNote:
- SendNoteEvent(
- date,
- UPSTtoCint(port),
- UPSTtoCint(chan),
- UPSTtoCint(data1),
- UPSTtoCint(data2),
- UPSTtoCint(data3));
- break;
-
- case typeCtrlChange:
- SendControlEvent(
- date,
- UPSTtoCint(port),
- UPSTtoCint(chan),
- UPSTtoCint(data1),
- UPSTtoCint(data2));
- break;
-
- case typeProgChange:
- SendProgramEvent(
- date,
- UPSTtoCint(port),
- UPSTtoCint(chan),
- UPSTtoCint(data1));
- break;
- };
-
- UPreturnHandle(rcvr);
- }
-
-
-
-
- /********************************************************************************/
- /* USER PRIMITIVES INSTALLATION */
- /********************************************************************************/
-
-
- char* UPinstall()
- {
- UPaddPrimitive(11001, UPMidiSharePresent, 0);
- UPaddPrimitive(11002, UPMidiGetVersion, 0);
- UPaddPrimitive(11003, UPMidiOpen, 0);
- UPaddPrimitive(11004, UPMidiClose, 0);
- UPaddPrimitive(11005, UPMidiGetTime, 0);
- UPaddPrimitive(11015, UPMidiGetClock, 0);
-
- UPaddPrimitive(11006, UPMidiSendEvent, 7);
-
- UPaddPrimitive(11020, UPMidiGetTotalSpace, 0);
- UPaddPrimitive(11021, UPMidiGetFreeSpace, 0);
- UPaddPrimitive(11022, UPMidiSetTiming, 4);
-
- UPaddPrimitive(11030, UPMidiStop, 0);
- UPaddPrimitive(11031, UPMidiStart, 0);
-
- UPaddPrimitive(11042, UPMidiGetEvent, 0);
- UPaddPrimitive(11043, UPMidiClearEvents, 0);
-
- return "MidiShare User Primitives";
- }
-
- char *versionString =
- "Objectworks\\Smalltalk(R) Release 4.1\nwith MidiShare™ Interface";
-
- char *resourceClassName = "St80";
-
-
-
- /*
- * UPInitLinkRegistry
- *
- * All statically linked procedures accessible to
- * the Objectkit Smalltalk C Programming kit
- * must be defined in this function using
- * UPRegisterSymbolAndHandle(char *, void *).
- */
-
- void
- UPInitLinkRegistry()
- {
- }
-
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- return st80Main(argc, argv, (char **)0);
- }
-